import os
import shutil
import subprocess

from pyx_package.script import BaseBehavior
from pyx_package.ps_paramete import PsParameter

from time import sleep
PYX_MODULE_NAME = "py-pyd"

class ScriptBehavior(BaseBehavior):

    def __init__(self) -> None:
        super().__init__()
        
        self.SetExeMode("function")
        
        self.InitParams()


    def InitParams(self):
        
        #需要处理的文件路径
        self.p_file_path = self.CreateParam(
            "file_path", "文件路径", PsParameter.Input, str, "")
        
        #解释器路径
        self.p_python_path = self.CreateParam(
            "python_path", "python 解释器路径", PsParameter.Input, str, "")
        self.p_python_path.keep_value = True

        #setup文件编码
        self.p_setup_code = self.CreateParam(
            "setup decode", "编译中间文件编码", PsParameter.Input, str, 'GBK')
        self.p_setup_code.value_input_mode = PsParameter.ComboBoxMode
        self.p_setup_code.SetOptionitems(['GBK', 'UTF-8'])
        self.p_setup_code.must = False
            
        #是否删除原python文件
        self.p_is_remove_scr_file = self.CreateParam(
            "remove_src_file", "删除源文件", PsParameter.Input, bool)
        self.p_is_remove_scr_file.value = False
        self.p_is_remove_scr_file.keep_value = True

        self._dir = None
        self._file_name = None
        self.__setup_path = None

    def DoStep(self):
    
        #格式化路径
        path = self.PathFormat(self.p_file_path.value)

        
        python_path = self.p_python_path.value
        if not os.path.isfile(python_path): 
            self.Error("找不到python解释器")
            return
        
        if not self.IsValid(path): 
            return 

        #创建setup.py文件
        self.InitSetupFile()
        cmd = python_path + " " + "\"" + self.__setup_path + "\"" + " build_ext --inplace"
        
        #调用外部命令执行
        popen = subprocess.Popen(cmd, cwd=self._dir, shell=True)
        popen.wait()
        
        if popen.poll() != 0:
            self.Debug("pyd创建失败:"+ path, "error")
        
        else:
            #判断是否删除源文件
            if self.p_is_remove_scr_file.value:
                os.remove(self.p_file_path.value)
                
        #删除setup文件与一些中间文件
        self.ClearTempFiles()
        
        
    def InitSetupFile(self):
        '''
            初始化setup文件
                module_path
        '''
        #获取文件路径
        self.__setup_path = self._dir + "/" + ".setup.py"
        
        '''
            根据当前系统类型，确定setup文件的字符编码
            
            window就用gbk
            不是window就是utf-8
        '''

        code_str = self.p_setup_code.value

        self.__setup_file_text = "# encoding={}\r\n".format(code_str) + \
        "from distutils.core import setup\r\nfrom Cython.Build import cythonize\r\nsetup(ext_modules=cythonize(\"{}\"))"
        
        with open(self.__setup_path,'w',encoding=code_str) as fp:
            fp.write(self.__setup_file_text.format(self.PathFormat(self.p_file_path.value)))
    
    def ClearTempFiles(self):
        '''
            清空临时文件
        '''
        
        #删除多余的文件
        setup_file = self._dir + "/" + ".setup.py"
        build_file = self._dir + "/" + "build"
        c_file = self._dir + "/" + self._file_name[:-3] + ".c"
        html_file = self._dir + "/" + self._file_name + ".html"

        try:
            if os.path.isdir(build_file):
                shutil.rmtree(build_file)
            if os.path.isfile(setup_file):
                os.remove(setup_file)
            if os.path.isfile(c_file):
                os.remove(c_file)
            if os.path.exists(html_file):
                os.remove(html_file)

        except:
            pass
            
    def IsValid(self, path) -> bool:
        '''
            判断文件有效性
        '''
        #判断文件有效性
        if not os.path.isfile(path):
            return False
        
        #解析所在目录与文件名称
        rIndex = path.rindex("/")
        self._dir = path[:rIndex]
        self._file_name = path[rIndex + 1:]

        #判断是否是.py结尾的文件
        rindex = self._file_name.rindex(".")
        suffix = self._file_name[rindex:]

        if suffix != ".py" and suffix != ".pyx": 
            return False
        
        #有效
        return True

    def PathFormat(self, path):
        '''
            将给定路径进行格式化
                1. 将所有的\\ 替换为/
                2. 删除最后一位的/
        '''
        path = path.replace("\\", "/")
        path = path.strip().rstrip("/")

        return path

    
    def GetDirAndNameByPath(self, path: str):
        """获取文件所在文件夹路径
            这个函数会将字符串中所有的\替换为/
        
        Keyword arguments:
        argument -- 文件全路径
        Return: 文件夹路径  文件名称
        """
        if "\\" not in path and "/" not in path:
            return None, None

        #替换/
        path = path.replace("\\", "/")
        rIndex = path.rindex("/")

        #返回解析后的文件路径，和文件名称
        return path[:rIndex], path[rIndex+1:]
        